/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "3D视口工作区.h"

#include <场景/intern/S_Scene.h>
#include <物体/S_摄像机.h>

#include "异步解算/物理异步解算.h"

#include "A_引擎/引擎.h"
#include "B_场景管理/相机/相机控制.h"
#include "B_场景管理/辅助物体更新.h"
#include "物体管理/渲染物体管理.h"
#include "物体编辑/3D控制手柄.h"
#include "物体编辑/物体编辑.h"
#include "物体编辑/视口辅助物体.h"

#include "../ui属性栏.h"

#include "框架/工作区/节点视口/ui节点面板.h"
#include "框架/工作区/节点视口/ui节点视口.h"
#include "框架/工作区/节点视口/ui节点创建菜单.h"

#include "ui3D场景视口.h"

#include <几何图形/图形相交.h>
#include <节点/空间/场景信息.h>




static std::set<C_工作区页面*> gui_3D视口工作区;

static C_Widget*	m_3D视口创建弹出菜单 = nullptr;
static C_Widget*	m_3D视口删除弹出菜单 = nullptr;
static C_Widget*	m_3D视口插帧弹出菜单 = nullptr;
static C_Widget*	g3D视口弹出菜单_渲染世界 = nullptr;
static C_Widget*	g3D视口弹出菜单_物体添加到渲染层 = nullptr;
static bool			g多选物体 = false;



static vec3		g拾取点到手柄相对位置 = {};
//static vec3		g手柄轴方向 = {};
static float32	g视线方向初始角度_X;
static float32	g视线方向初始角度_Y;
static vec3     g选择中心 = {};






static void f_取消变换操作(S_摄像机& camera, bool 重构变换矩阵 = false) {
	
	S_Tranform 手柄还原变换 = f_tranformIdentity();

	switch (S_框架::g_物体变换方式) {
		case E_变换::e_移动:
			手柄还原变换 = f_控制手柄_取消移动物体(!重构变换矩阵);
			break;
		case E_变换::e_旋转:
			手柄还原变换 = f_控制手柄_取消旋转物体(!重构变换矩阵);
			break;
		case E_变换::e_缩放:
			手柄还原变换 = f_控制手柄_取消缩放物体(!重构变换矩阵);
			break;
	}



	if (重构变换矩阵) {
		for (auto* ob : S_框架::g_拾取物体) {
			Mat44f 父级变换 = f_mat44_identity();
			if (ob->m_父对象 && ob->m_父对象->m_Type != E_物体类型::t_空) {
				auto* pob = dynamic_cast<S_物体*>(ob->m_父对象);
				父级变换 = f_ob_get变换矩阵(pob, pob->m_实例ID);
			}
			f_ob_更新变换约束(ob, &父级变换);
		}
	}
	else {
		
	}
	f_view3d_置变换手柄变换(手柄还原变换);
	

	S_框架::g_标记变换更新后事件 = 2;
}

static void f_完成变换操作(C_3D场景视口* view, E_鼠标按钮 鼠标按钮) {
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	switch (鼠标按钮) {
		case E_鼠标按钮::e_鼠标左键: {
			if (S_框架::g_变换开关) {
				S_框架::g_标记变换更新后事件 = 2;

				f_控制手柄_完成变换(S_框架::g_物体变换方式);
				f_camera_set偏移视点(*camera, f_global_get激活物体包围中心点());
				f_3D视口工作区_更新所有视口组件绘制();
			}
			break;
		}
	}
	
	S_框架::g_变换开关 = false;
}
//static bool f_准备变换操作(C_3D场景视口* view) {
//	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
//
//	if (S_框架::g_变换开关) {
//		f_取消变换操作(*camera, true);
//		f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
//	}
//	else {
//		f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(view));
//		f_控制手柄_准备移动物体(view->m_变换手柄, true);
//	}
//}

static void f_变换开始拾取点初始化(S_物体* 手柄, S_摄像机* camera, const vec2& 鼠标局部位置, const S_Rect2Df& rect) {
	vec3 射线[2];
	S_射线拾取参数::g结束射线		= f_scene_构建屏幕射线(_Vec3(鼠标局部位置), *camera, rect, 射线);
	S_射线拾取参数::g手柄初始变换	= 手柄->f_get位置();

	
	vec3 视线向量 = f_camera_get视线向量(*camera);
	switch (S_框架::g_操作变换轴) {
		case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
		case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
		case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;

		case E_轴向::e_XY: 视线向量 = vec3{ 0, 0, 1 }; break;
		case E_轴向::e_XZ: 视线向量 = vec3{ 0, 1, 0 }; break;
		case E_轴向::e_YZ: 视线向量 = vec3{ 1, 0, 0 }; break;
		default:
			break;
	}
	视线向量 = normalize(视线向量);

	auto 中心坐标 = 手柄->m_变换.position;
	vec4 拾取平面 = f_graph_坐标构建平面(中心坐标, 视线向量);


	f_graph_线段平面相交(射线[0], 射线[1], 拾取平面, S_射线拾取参数::g交点S);
	switch (S_框架::g_操作变换轴) {
		case E_轴向::e_X: S_射线拾取参数::g交点S.y = 中心坐标.y; S_射线拾取参数::g交点S.z = 中心坐标.z; break;
		case E_轴向::e_Y: S_射线拾取参数::g交点S.x = 中心坐标.x; S_射线拾取参数::g交点S.z = 中心坐标.z; break;
		case E_轴向::e_Z: S_射线拾取参数::g交点S.x = 中心坐标.x; S_射线拾取参数::g交点S.y = 中心坐标.y; break;

		case E_轴向::e_XY: S_射线拾取参数::g交点S.z = 中心坐标.z; break;
		case E_轴向::e_XZ: S_射线拾取参数::g交点S.y = 中心坐标.y; break;
		case E_轴向::e_YZ: S_射线拾取参数::g交点S.x = 中心坐标.x; break;
	}
	
	
	g拾取点到手柄相对位置 = 中心坐标 - S_射线拾取参数::g交点S;
	vec3 scal = _Vec3(1.0) / 手柄->f_get缩放();
	//vec3 scal = _Vec3(1.0);
	switch (S_框架::g_操作变换轴) {
		case E_轴向::e_X: g拾取点到手柄相对位置.x *= scal.x; break;
		case E_轴向::e_Y: g拾取点到手柄相对位置.y *= scal.y; break;
		case E_轴向::e_Z: g拾取点到手柄相对位置.z *= scal.z; break;

		case E_轴向::e_XY: g拾取点到手柄相对位置.x *= scal.x; g拾取点到手柄相对位置.y *= scal.y; break;
		case E_轴向::e_XZ: g拾取点到手柄相对位置.x *= scal.x; g拾取点到手柄相对位置.z *= scal.z; break;
		case E_轴向::e_YZ: g拾取点到手柄相对位置.y *= scal.y; g拾取点到手柄相对位置.z *= scal.z; break;
	}
	std::cout<<"-------- S_射线拾取参数::g交点S = " << S_射线拾取参数::g交点S.x << " " << S_射线拾取参数::g交点S.y << " " << S_射线拾取参数::g交点S.z << "\n";
	std::cout<<"中心坐标 = " << 中心坐标.x << " " << 中心坐标.y << " " << 中心坐标.z << "\n";
	std::cout<<"** -- ** g拾取点到手柄相对位置 = " << g拾取点到手柄相对位置.x << " " << g拾取点到手柄相对位置.y << " " << g拾取点到手柄相对位置.z << "\n";
	std::cout<<"S_射线拾取参数::gscalS = " << scal.x << " " << scal.y << " " << scal.z << "\n";
	std::cout<<"S_射线拾取参数::g手柄初始变换 = " << S_射线拾取参数::g手柄初始变换.x << " " << S_射线拾取参数::g手柄初始变换.y << " " << S_射线拾取参数::g手柄初始变换.z << "\n";
	std::cout<<"S_框架::g_操作变换轴 = " << S_框架::g_操作变换轴 << "\n";
}

static bool f_拾取操作手柄(S_物体* 手柄, S_摄像机& camera, const S_Rect2Df& rect) {
	
	if (C_3D场景视口::g视口摄像机旋转) {
		S_框架::g_操作变换轴 = E_轴向::e_None轴向;
	}
	else {
		vec3 坐标 = { S_框架::g_鼠标起始坐标.x, S_框架::g_鼠标起始坐标.y, 0.001f };
		vec3 射线方向 = f_scene_构建屏幕射线(坐标, camera, rect, S_节点数据::g_视口鼠标点射线);
		
		if (手柄->m_显示 && !S_框架::g_变换开关) {
			//S_射线拾取参数::g手柄初始变换	= 手柄->f_get位置();
			S_射线拾取参数::g相机位置		= f_camera_get眼睛位置(camera);

			if (S_框架::g_物体变换方式 == E_变换::e_变换_None) {
				
			}
			auto 变换轴 = f_变换手柄_拾取(手柄, S_框架::g_鼠标起始坐标, rect, S_节点数据::g_视口鼠标点射线[0], 射线方向, camera);
			if (S_框架::g_操作变换轴 != 变换轴) {
				S_框架::g_操作变换轴 = 变换轴;
				return true;
			}
		}
	}

	return false;
}

static E_事件是否传递 on_3D视口鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	auto camera	= f_ui_get3D视口摄像机(view->ui_三维视口);
	auto rect	= view->ui_三维视口->f_getRect();
	S_框架::g_鼠标起始坐标 = f_view3d_get平面鼠标位置(view->ui_三维视口);


	auto 偏移位置 = f_3dView_屏幕坐标转相机偏移(*camera, S_框架::g_鼠标起始坐标, camera->m_视点, rect);
	f_camera_开始相机变换(*camera, 偏移位置);

	switch (按钮) {
		case E_鼠标按钮::e_鼠标左键: {
			C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_鼠标左键;
			C_3D场景视口::g鼠标左键是否按下 = true;
			

			if (S_框架::g_变换开关) {
				//对应已经用快捷键开启变化

			}
			else {
				//对应用控制变化手柄开始变化
				S_框架::g_变换开关 = S_框架::g_操作变换轴 != E_轴向::e_None轴向;
				S_框架::g_变换开关 &= !C_3D场景视口::g视口摄像机旋转;
				S_框架::g_变换开关 &= !(C_3D场景视口::g视口摄像机平移 & C_3D场景视口::g_移动视口_键盘按键);


				if ( S_框架::g_变换开关 ) {
					f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, rect);

					switch (S_框架::g_变换手柄类型) {
						case E_变换::e_变换_None:
						case E_变换::e_移动:
							f_变换_准备移动物体(view->m_变换手柄, true);
							break;
						case E_变换::e_旋转:
							f_控制手柄_准备旋转物体(view->m_变换手柄, S_框架::g_鼠标起始坐标, rect, camera);
							break;
						case E_变换::e_缩放:
							f_控制手柄_准备缩放物体(view->m_变换手柄, S_框架::g_鼠标起始坐标, rect, camera);
							break;
						default:
							S_框架::g_变换开关 = false;
							break;
					}
				}
			}

			break;
		}
		
		case E_鼠标按钮::e_鼠标中键: {
			//C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_鼠标中键;
			//S_Core::g_视线向量 = f_camera_get视线向量(S_Core::g_相机);
		}
		break;
		case E_鼠标按钮::e_鼠标右键: {
			

			break;
		}
			
			
	}

	
	//std::cout << "f_鼠标按下:" << S_框架::g_鼠标起始坐标.y << " = " << std::endl;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self->m_父部件);
	auto* camera = f_ui_get3D视口摄像机(self);
	

	switch (按钮) {
		case E_鼠标按钮::e_鼠标左键: {
			C_3D场景视口::g视口摄像机平移 &= (0xffffffff ^ C_3D场景视口::g_移动视口_鼠标左键);
			C_3D场景视口::g鼠标左键是否按下 = false;
			
			S_节点数据::g_开启节点更新 = true;
			view->m_是否开启视线旋转物体 = true;
			break;
		}

		case E_鼠标按钮::e_鼠标中键: {
			C_3D场景视口::g视口摄像机平移 &= (0xffffffff ^ C_3D场景视口::g_移动视口_鼠标中键);
			break;
		}
		
		case E_鼠标按钮::e_鼠标右键: {
			//f_取消变换操作(*camera);
			//f_view3d_置变换手柄变换(S_框架::g_变换手柄属性);
			//f_view3d_缩放所有视口变换手柄();
			//f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_变换物体);
			break;
		}
	}

	

	C_3D场景视口::g视口摄像机平移 &= (C_3D场景视口::g_移动视口_鼠标左键 | C_3D场景视口::g_移动视口_鼠标中键);
	f_完成变换操作(view, 按钮);

	
	f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
	f_3dView_开关物体数值输入(*view, false);

	view->f_关闭虚拟线绘制();
	view->m_是否开启视线旋转物体 = false;
	//f_widget_更新绘制(view);
	return E_事件是否传递::e_事件传递_终止;
}


static E_事件是否传递 on_鼠标位置改变(C_Widget* self, const ivec4& mouse) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	
	auto rect = f_ui_get视口(view->ui_三维视口);
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
	vec2 坐标 = f_view3d_get平面鼠标位置(view->ui_三维视口);

	if (S_框架::g_操作变换轴 != E_轴向::e_None轴向 < 0 && C_3D场景视口::g鼠标左键是否按下 && !C_3D场景视口::g视口摄像机平移) {
		if (f_prop_Bool(S_节点数据::g_物理引擎视口互交)) {
			vec3 射线方向 = f_scene_构建屏幕射线(_Vec3(坐标), *camera, rect, S_节点数据::g_视口鼠标点射线);

			f_工作区_变换物体(view, E_键位执行状态::e_执行);
			return E_事件是否传递::e_事件传递_继续;
		}
	}

	if (C_3D场景视口::g视口摄像机旋转 || C_3D场景视口::g视口摄像机平移) {
		return E_事件是否传递::e_事件传递_终止;
	}
	else {
		if (S_框架::g_变换开关) {
			f_工作区_变换物体(view, E_键位执行状态::e_执行);
			return E_事件是否传递::e_事件传递_终止;
		}

		S_框架::g_鼠标起始坐标 = {坐标.x, 坐标.y};
		if (f_拾取操作手柄(view->m_变换手柄, *camera, rect)) {
			f_widget_更新绘制(view->ui_三维视口);
		}
	}
	
	return E_事件是否传递::e_事件传递_终止;
}


static E_事件是否传递 on_鼠标滚轮(C_Widget* self, const S_鼠标& 轮值) {
	//f_ob_set缩放(S_Core::g_旋转变换手柄, { dis, dis, dis });
	return E_事件是否传递::e_事件传递_终止;
}


static E_事件是否传递 on_3D视口键盘按键按下(C_Widget* self, const S_键盘& ks) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	if (ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_按下) {
		//C_3D场景视口::g视口摄像机旋转 = true;
	}
	else if (ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_放开 || ks.Keys状态[S_InputKey::e_KEY_左ALT] == DEF_按键状态_准备) {
		C_3D场景视口::g视口摄像机旋转 = false;
	}
	else {
		
	}


	if (ks.Keys状态[S_InputKey::e_KEY_左SHIFT] == DEF_按键状态_按下) {
		C_3D场景视口::g视口摄像机平移 |= C_3D场景视口::g_移动视口_键盘按键;
	}
	else if (ks.Keys状态[S_InputKey::e_KEY_左SHIFT] == DEF_按键状态_放开) {
		//C_3D场景视口::g视口摄像机平移 &= (C_3D场景视口::g_移动视口_鼠标左键 | C_3D场景视口::g_移动视口_键盘按键);
		C_3D场景视口::g视口摄像机平移 &= (0xffffffff ^ C_3D场景视口::g_移动视口_键盘按键);
		g多选物体 = false;
	}



	if (S_框架::g_拾取物体.size()) {
		switch (S_框架::g当前编辑对象类型) {
		case E_物体类型::t_网格物体: {
			f_view3d_物体编辑模式_键盘事件(ks);
			break;
		}
		case E_物体类型::t_骨架: 
		case E_物体类型::t_骨骼: {
			f_view3d_骨骼编辑模式_键盘事件(self, ks, *self->m_UIctx, camera);
			break;
		}
		
		case E_物体类型::t_摄像机: {
			break;
		}
		default:
			break;
		}
	}

	

	return E_事件是否传递::e_事件传递_终止;
}





static bool on_3D场景视口打开关闭(C_Widget* self, bool show) {
	C_工作区页面* 工作区 = dynamic_cast<C_工作区页面*>(self);
	C_3D场景视口* view = dynamic_cast<C_3D场景视口*>(工作区->mui_视口页面);

	if (show) {
		S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_属性栏);
		S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_状态条);

		S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(view->ui_操作图形层);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(view->ui_坐标组件);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(view->ui_透视模式组件);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(view->ui_移动视口组件);
	}
	else {
		S_框架::m_工作区属性面板渲染层ID分配.f_移除渲染层组件(工作区->mui_属性栏);
		S_框架::m_工作区属性面板渲染层ID分配.f_移除渲染层组件(工作区->mui_状态条);

		S_框架::m_工作区视口内部面板渲染层ID分配.f_移除渲染层组件(view->ui_操作图形层);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_移除渲染层组件(view->ui_坐标组件);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_移除渲染层组件(view->ui_透视模式组件);
		//S_框架::m_工作区视口内部面板渲染层ID分配.f_移除渲染层组件(view->ui_移动视口组件);
	}

	return false;
}

C_工作区页面* f_工作区_创建3D视口(S_UI渲染环境& ctx) {
	auto* ui_视口 = new C_3D场景视口(ctx);
	auto ui_状态条 = new C_状态条(ctx);

	ui_视口->mf_鼠标移动					= on_鼠标位置改变;
	ui_视口->mf_鼠标按键按下				= on_3D视口鼠标按下;
	ui_视口->ui_三维视口->mf_鼠标按键放开	= on_鼠标放开;
	ui_视口->ui_三维视口->mf_鼠标滚轮		= on_鼠标滚轮;
	ui_视口->mf_键盘按键敲击				= on_3D视口键盘按键按下;

	
	C_工作区页面* 工作区 = new C_工作区页面(E_工作区类型::e_3D视口, ctx, E_方向::e_横向, ui_视口, ui_状态条);

	工作区->mf_打开关闭	= on_3D场景视口打开关闭;
	ui_视口->ui_属性栏	= 工作区->mui_属性栏;
	ui_视口->ui_状态条	= 工作区->mui_状态条;

	f_view3d_重构状态条(工作区->mui_状态条, ui_视口->ui_三维视口);


	S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_属性栏);
	S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_状态条);

	S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(ui_视口->ui_操作图形层);
	//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(ui_视口->ui_坐标组件);
	//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(ui_视口->ui_透视模式组件);
	//S_框架::m_工作区视口内部面板渲染层ID分配.f_置组件渲染层(ui_视口->ui_移动视口组件);
	
	gui_3D视口工作区.insert(工作区);




	S_拖拽键位映射* 拖放键位;

	拖放键位 = f_widget_init_拖放键位映射();
	拖放键位->event = f_工作区_移动摄像机;
	拖放键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	拖放键位->键盘状态[0] = DEF_按键状态_按下中;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)拖放键位, u"键盘移动视口", u"移动视口");

	拖放键位 = f_widget_init_拖放键位映射();
	拖放键位->event = f_工作区_移动摄像机;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_中键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)拖放键位, u"鼠标移动视口", u"移动视口");

	拖放键位 = f_widget_init_拖放键位映射();
	拖放键位->event = f_工作区_旋转摄像机;
	拖放键位->键盘按键[0] = S_InputKey::e_KEY_左ALT;
	拖放键位->键盘状态[0] = DEF_按键状态_按下中;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)拖放键位, u"旋转视口", u"旋转视口");

	拖放键位 = f_widget_init_拖放键位映射();
	拖放键位->event = f_工作区_变换物体;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)拖放键位, u"变换物体", u"变换物体");

	拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_物体框选排除;
	拖放键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	拖放键位->键盘状态[0] = DEF_按键状态_按下中;
	拖放键位->键盘按键[1] = S_InputKey::e_KEY_左ALT;
	拖放键位->键盘状态[1] = DEF_按键状态_按下中;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下中;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)拖放键位, u"框选排除", u"框选排除");

	拖放键位 = f_widget_init_拖拽键位映射();
	拖放键位->event = f_工作区_物体框选;
	拖放键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖放键位->鼠标状态[0] = DEF_按键状态_按下中 | DEF_按键状态_按下;
	拖放键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)拖放键位, u"框选", u"框选");



	S_键盘键位映射* 快捷键;
	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_开启多选操作;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	快捷键->键盘状态[0] = DEF_按键状态_按下中 | DEF_按键状态_按下;
	快捷键->发生组件 = ui_视口->ui_操作图形层;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"开启加选", u"开启加选");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_切换摄像机投影模式;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_5;
	快捷键->键盘状态[0] = DEF_按键状态_放开;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"切换摄像机透射模式", u"投影模式");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到激活物体中心;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_点;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"移动到激活物体中心", u"移动到激活物体中心");


	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到前;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_1;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"前视图", u"前视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到后;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_3;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"后视图", u"后视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到左;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_4;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"左视图", u"左视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到右;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_6;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"右视图", u"右视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到上;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_8;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"顶视图", u"顶视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_镜头视点移动到下;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_2;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"底视图", u"底视图");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_设置激活摄像机为视口摄像机;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_小键盘数字键_0;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_三维视口, (S_键位映射*)快捷键, u"设置视图摄像机", u"设置视图摄像机");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_打开关键帧插入菜单;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_I;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"插入关键帧", u"插入关键帧");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_view3d_物体添加到渲染层;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_M;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"添加到渲染层", u"添加到渲染层");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_打开创建菜单;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_TAB;
	快捷键->键盘状态[0] = DEF_按键状态_放开;
	//f_ui_注册键盘快捷键(ui_视口, 快捷键);
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"打开物体添加菜单", u"添加物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_移动物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_G;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"移动物体", u"移动物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_旋转物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_R;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"旋转物体", u"旋转物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_缩放物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_S;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"缩放物体", u"缩放物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_复制物体;
	快捷键->发生组件 = ui_视口;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	快捷键->键盘状态[0] = DEF_按键状态_按下中;
	快捷键->键盘按键[1] = S_InputKey::e_KEY_D;
	快捷键->键盘状态[1] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"复制物体", u"复制物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_删除物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_X;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)快捷键, u"删除物体", u"删除物体");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_物体反选;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	快捷键->键盘状态[0] = DEF_按键状态_按下中;
	快捷键->键盘按键[1] = S_InputKey::e_KEY_I;
	快捷键->键盘状态[1] = DEF_按键状态_按下;
	快捷键->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"反选物体", u"反选物体");


	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_X方向变换物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_X;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"X变换", u"X变换");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_Y方向变换物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_Y;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"Y变换", u"Y变换");

	快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_Z方向变换物体;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_Z;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)快捷键, u"Z变换", u"Z变换");




	S_鼠标键位映射* 鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_推拉摄像机;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui_视口;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口, (S_键位映射*)鼠标键位, u"推拉摄像机", u"推拉摄像机");

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_物体加选;
	鼠标键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	鼠标键位->键盘状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	鼠标键位->发生组件 = 工作区;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)鼠标键位, u"物体加选", u"物体加选");

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_物体单选;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	鼠标键位->发生组件 = 工作区;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_操作图形层, (S_键位映射*)鼠标键位, u"物体单选", u"物体单选");

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_方向小组件点击;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_放开;
	鼠标键位->发生组件 = ui_视口->ui_坐标组件;
	C_键位映射配置::f_添加3D视口操作键位(ui_视口->ui_坐标组件, (S_键位映射*)鼠标键位, u"视图方向", u"视图方向");


	f_ui_整理快捷键(ui_视口);
	f_ui_整理快捷键(ui_视口->ui_三维视口);
	f_ui_整理快捷键(ui_视口->ui_坐标组件);
	f_ui_整理快捷键(ui_视口->ui_操作图形层);

    return 工作区;
}

void f_3D视口工作区_销毁(C_工作区页面* 工作区) {
	gui_3D视口工作区.erase(工作区);

	delete 工作区->mui_视口页面;
	delete 工作区->mui_属性栏;
	delete 工作区->mui_状态条;

	delete 工作区;
}









bool on_2级3D视口创建菜单项(C_Widget* self, const std::u16string name, uint16 id) {
	return false;
}

bool on_2级3D视口创建物体项(C_Widget* self, const std::u16string name, uint16 id) {
	if (S_节点数据::g_物体节点树.size()) {
		C_节点树* t = (C_节点树*)(S_节点数据::g_物体节点树.front().m_Ptr);
	}
	f_NodeView_设置当前节点添加_树类型限制(E_节点树类型::e_type_物体节点树);

	f_NodeView_设置节点面板局部添加位置(nullptr, {});
	on_2级物体节点创建菜单项(self, name, id);

	if (name == u"骨架") {
		f_NodeView_设置节点面板局部添加位置(nullptr, {});
		auto 骨架节点 = f_global_get激活节点();
		on_2级物体节点创建菜单项(self, u"骨头", id);
		auto 骨骼节点 = f_global_get激活节点();

		uint32 num = 骨架节点.size();
		assert(骨架节点.size() && 骨架节点.size() == 骨骼节点.size());
		for (uint32 i = 0; i < num; ++i) {
			auto ia = 骨骼节点[i]->m_包含在多个视口的UI部件.begin();
			auto ib = 骨架节点[i]->m_包含在多个视口的UI部件.begin();
			
			f_NodePanel_链接节点((C_节点面板*)*ia, 1, (C_节点面板*)*ib, 1);
		}
	}

	return false;
}


static bool on_1级创建菜单项(C_Widget* self, const std::u16string, uint16 id) {
	return false;
}

static bool on_1级菜单项_物体关键帧插入(C_Widget* self, const std::u16string name, uint16 id) {
	uint32 变换类型 = 0;

	if (name == u"移动") {
		变换类型 |= 1;
	} else if (name == u"旋转") {
		变换类型 |= 2;
	} else if (name == u"缩放") {
		变换类型 |= 4;
	}

	f_OE_物体变换插帧(变换类型);

	f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_所有);

	return false;
}


static S_Object* g当前选择渲染世界 = nullptr;


static bool on_2级菜单项_物体添加到渲染层(C_Widget* self, const std::u16string name, uint16 id) {
	f_OE_物体添加到渲染层(S_节点数据::g_渲染层数据[name], S_框架::g_拾取物体);
	f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_拾取物体);
	return false;
}

static bool on_1级菜单项_物体渲染层菜单项创建(C_Widget* self, const std::u16string name, uint16 id) {
	uint32 变换类型 = 0;

	S_菜单创建参数 创建项;
	创建项.mf_菜单项点击 = on_2级菜单项_物体添加到渲染层;
	
	g当前选择渲染世界 = S_节点数据::g_渲染世界数据[name];
	for (auto& e : g当前选择渲染世界->m_子物体) {
		创建项.item.push_back({ e->m_Name, u"", 0 });
	}

	
	f_ui_填充菜单项(g3D视口弹出菜单_物体添加到渲染层, 创建项, 2);
	f_ui_弹出子菜单(self, g3D视口弹出菜单_物体添加到渲染层);

	return true;
}




void f_工作区页面_3D视口界面初始化(S_UI渲染环境& ctx) {
	
	S_菜单创建参数 基本几何体创建参数 = {
		f_view3d_创建物体菜单, {

			{u"平面", u"",  u"",0},
			{u"球体", u"",  u"",0},
			//{u"圆环", "",  u"",0},
			{u"方体", u"",  u"",0},
			{u"圆柱", u"",  u"",0},
			{u"圆锥", u"",  u"",0},
			//{u"六面", "", 0},
			//{u"线框立方体", u"四边顶点", 0},
		}
	};

	S_菜单创建参数 物体创建参数 = {
		on_2级物体节点创建菜单项, {

			{u"目标相机", u"目标相机",  u"",0},
			{u"虚拟体", u"",  u"",0},
			//{u"线框立方体", "四边顶点", 0},
		}
	};


	S_菜单创建参数 骨骼创建参数 = {
		on_2级3D视口创建物体项, {
			{u"骨架",	u"",  u"",0},
			{u"IK",		u"",  u"",0},
		}
	};

	auto 灯光项 = f_menu参数_灯光();

	S_菜单创建参数 菜单创建参数 = {
		on_1级创建菜单项, {
			{u"网格", u"三角网格", u"", & 基本几何体创建参数},
			//{u"物体", u"物体", &物体创建参数},
			//{u"骨骼", "bone", &骨骼创建参数},
			//{u"灯光", u"font-61452", &灯光项},
			//{u"物理", "orbital", &物理创建参数},
		}
	};

	S_菜单创建参数 菜单删除参数 = {
		f_view3d_删除物体菜单, {
			{ u"删除", u"删除", u"X", nullptr },
		}
	};

	m_3D视口创建弹出菜单 = f_ui_创建菜单(ctx, e_纵向, 菜单创建参数);
	m_3D视口删除弹出菜单 = f_ui_创建菜单(ctx, e_纵向, 菜单删除参数);

	S_菜单创建参数 关键帧菜单创建参数 = {
		on_1级菜单项_物体关键帧插入, {
			{u"移动", u"font-475",  u"",0},
			{u"旋转", u"04",  u"",0},
			{u"缩放", u"top_right_expand",  u"",0},
	}
	};
	m_3D视口插帧弹出菜单 = f_ui_创建菜单(ctx, e_纵向, 关键帧菜单创建参数);


	g3D视口弹出菜单_渲染世界 = f_ui_创建菜单(ctx, e_纵向, {});
	g3D视口弹出菜单_物体添加到渲染层 = f_ui_创建菜单(ctx, e_纵向, {});
	
}

void f_工作区页面_3D视口界面销毁() {
	delete m_3D视口创建弹出菜单;
	delete m_3D视口插帧弹出菜单;
	delete g3D视口弹出菜单_物体添加到渲染层;
	delete g3D视口弹出菜单_渲染世界;
}

void f_工作区_选择物体(C_工作区页面* 工作区页面, bool 是否加选) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(工作区页面->mui_视口页面);
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	//auto 投影比例 = f_ui_get空间投影比例(f_ui_get视口(view->ui_三维视口), camera.m_相机投影, camera.m_视点距离);
	if (S_框架::g_变换开关) {
		f_取消变换操作(*camera, S_框架::g_变换开关);
		S_框架::g_变换开关 = false;
		f_3dView_开关物体数值输入(*view, false);

		f_view3d_缩放所有视口变换手柄();
		//f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_变换物体);

		f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
	}
	else {
		auto rect = f_ui_get视口(view->ui_三维视口);
		auto 鼠标位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, view->ui_三维视口);
		vec3 坐标 = { 鼠标位置.x, rect.extent.y - 鼠标位置.y, 0.0f };

		vec3 射线[2];
		vec3 射线方向 = f_scene_构建屏幕射线(坐标, *camera, rect, 射线);


		if (f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式)) {
			if (S_框架::g_拾取物体.size()) {
				S_框架::g当前编辑对象类型 = f_ob_get可视对象类型(*S_框架::g_拾取物体.begin());

				vec3 中点{};
				bool 是否拾取 = false;
				switch (S_框架::g当前编辑对象类型) {
					
					case E_物体类型::t_网格物体: {
						if (f_prop_enum(S_节点数据状态::g_网格编辑模式)) {
							f_view3d_射线选中网格元素(射线[0], 射线[1], 是否加选, *camera);
						}
						else {

						}
						break;
					}

					case E_物体类型::t_骨骼:
					case E_物体类型::t_骨架: {
						if (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
							f_view3d_射线选中骨骼元素(射线[0], 射线[1], 是否加选, *camera);
						}
						else {

						}
						

						f_view3d_重构属性栏(工作区页面->mui_属性栏, S_框架::g_拾取物体, view->ui_三维视口);
						break;
					}

					case E_物体类型::t_摄像机: {
						break;
					}

					case E_物体类型::t_空间曲线: {
						Mat44f mat[2] = { *(Mat44f*)&camera->m_相机投影矩阵, *(Mat44f*)&camera->m_相机视图矩阵 };
						g选择中心 = {};
						是否拾取 = f_view3d_射线选中曲线元素(鼠标位置, 是否加选, mat, rect, g选择中心);
						break;
					}
					default:
						break;
				}

				if (是否拾取) {
					//S_框架::g_移动变换手柄->f_set位置(g选择中心, 0);
					f_camera_set偏移视点(*camera, g选择中心);
				}

				f_view3d_重构状态条(工作区页面->mui_状态条, view->ui_三维视口);
			}
		}
		else {
			f_控制手柄_准备变换(true);

			f_view3d_射线选中物体(射线[0], 射线方向, 是否加选, *camera, rect, 鼠标位置);

			if (S_框架::g_拾取物体.size()) {
				f_view3d_重构状态条(工作区页面->mui_状态条, view->ui_三维视口);
				f_view3d_重构属性栏(工作区页面->mui_属性栏, S_框架::g_拾取物体, view->ui_三维视口);

				f_view3d_缩放所有视口变换手柄();
			}

		}
	}
	f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_拾取物体);
	f_widget_更新绘制(view->ui_三维视口);
	
	S_节点数据::g_开启节点更新 = true;
}



E_事件是否传递 f_工作区_移动物体(C_Widget* self, E_键位执行状态 状态) {
	
	f_projectFile_设置文件保存状态(false);

	C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
	view->f_关闭虚拟线绘制();
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	S_框架::g_操作变换轴 = E_轴向::e_XYZ;
	S_框架::g_视线向量 = f_camera_get视线向量(*camera);
	S_框架::g_鼠标起始坐标 = f_view3d_get平面鼠标位置(self);
	auto rect = f_ui_get视口(self);



	if (S_框架::g_变换开关) {
		f_取消变换操作(*camera, true);
		f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
	}
	else {
		f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
		f_变换_准备移动物体(view->m_变换手柄, true);
	}


	S_框架::g_变换开关		= true;
	S_框架::g_物体变换方式	= E_变换::e_移动;
	

	

	if (f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式)) {
		switch (S_框架::g当前编辑对象类型) {
			case E_物体类型::t_空间曲线:
			case E_物体类型::t_多边形:
			case E_物体类型::t_网格物体: {
				//goto To_移动;
				break;
			}
			case E_物体类型::t_骨架:
			case E_物体类型::t_骨骼: {
				if (f_prop_enum(S_节点数据状态::g_骨架编辑模式) == E_骨骼编辑模式::e_姿态模式) {
					if (f_prop_enum(S_节点数据状态::g_骨骼姿态编辑模式) == 0) {
						f_工作区_旋转物体(self, E_键位执行状态::e_开始);
						break;
					}
				}
				//goto To_移动;
				break;
			}
			case E_物体类型::t_摄像机: {
				//goto To_移动;
				break;
			}
			default:
				break;
		}
	}
	else {
	//To_移动:
		
		
	}

	
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_旋转物体(C_Widget* self, E_键位执行状态 状态) {
	if (状态 == E_键位执行状态::e_开始) {
		f_projectFile_设置文件保存状态(false);

		C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
		if (view) {
			view->m_是否开启视线旋转物体 = true;
		}

		auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

		if (S_框架::g_变换开关) {
			f_取消变换操作(*camera, true);
			f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
		}
		f_3dView_开关物体数值输入(*view, true);


		S_框架::g_变换开关 = true;
		S_框架::g_操作变换轴 = E_轴向::e_XYZ;
		S_框架::g_物体变换方式 = E_变换::e_旋转;


		auto 鼠标位置 = f_view3d_get平面鼠标位置(self);
		S_射线拾取参数::g手柄初始变换 = view->m_变换手柄->f_get位置();
		f_控制手柄_准备旋转物体(view->m_变换手柄, 鼠标位置, self->f_getRect(), camera, false);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_缩放物体(C_Widget* self, E_键位执行状态 状态) {
	if (状态 == E_键位执行状态::e_开始) {
		f_projectFile_设置文件保存状态(false);

		C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
		if (S_框架::g_变换开关) {
			f_取消变换操作(*camera, true);
			f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_XYZ);
		}
		f_3dView_开关物体数值输入(*view, true);

		S_框架::g_变换开关 = true;
		S_框架::g_操作变换轴 = E_轴向::e_XYZ;
		S_框架::g_物体变换方式 = E_变换::e_缩放;


		S_射线拾取参数::g手柄初始变换 = view->m_变换手柄->f_get位置();
		auto 鼠标位置 = f_view3d_get平面鼠标位置(self);
		f_控制手柄_准备缩放物体(view->m_变换手柄, 鼠标位置, self->f_getRect(), camera, false);
	}
	return E_事件是否传递::e_事件传递_终止;
}


E_事件是否传递 f_工作区_X方向变换物体(C_Widget* self, E_键位执行状态 状态) {
	if (S_框架::g_变换开关) {
		if (状态 == E_键位执行状态::e_开始) {
			C_3D场景视口* view = static_cast<C_3D场景视口*>(self->m_父部件->m_父部件);
			auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
			f_取消变换操作(*camera, true);
			
			f_3dView_开关物体数值输入(*view, true);
			
			S_框架::g_操作变换轴 = E_轴向::e_X;
			f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
			f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_X);
		}
		return E_事件是否传递::e_事件传递_终止;
	}
	else {
		return E_事件是否传递::e_事件传递_继续;
	}
}

E_事件是否传递 f_工作区_Y方向变换物体(C_Widget* self, E_键位执行状态 状态) {
	if (S_框架::g_变换开关) {
		if (状态 == E_键位执行状态::e_开始) {
			C_3D场景视口* view = static_cast<C_3D场景视口*>(self->m_父部件->m_父部件);
			auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
			f_取消变换操作(*camera, true);
			
			f_3dView_开关物体数值输入(*view, true);

			S_框架::g_操作变换轴 = E_轴向::e_Y;
			f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
			f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_Y);
		}
		return E_事件是否传递::e_事件传递_终止;
	}
	else {
		return E_事件是否传递::e_事件传递_继续;
	}
}

E_事件是否传递 f_工作区_Z方向变换物体(C_Widget* self, E_键位执行状态 状态) {
	if (S_框架::g_变换开关) {
		if (状态 == E_键位执行状态::e_开始) {
			C_3D场景视口* view = static_cast<C_3D场景视口*>(self->m_父部件->m_父部件);
			auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
			f_取消变换操作(*camera, true);
			
			f_3dView_开关物体数值输入(*view, true);

			S_框架::g_操作变换轴 = E_轴向::e_Z;
			f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
			f_辅助物体_切换变换手柄轴显示(view->m_变换手柄, E_轴向::e_Z);
		}
		return E_事件是否传递::e_事件传递_终止;
	}
	else {
		return E_事件是否传递::e_事件传递_继续;
	}
}


E_事件是否传递 f_工作区_复制物体(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);
		C_3D场景视口* view = static_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

		f_OE_复制(S_框架::g_拾取物体, false);

		//f_变换开始拾取点初始化(view->m_变换手柄, camera, S_框架::g_鼠标起始坐标, f_ui_get视口(view));
		//f_控制手柄_准备移动物体(view->m_变换手柄, true);

		f_工作区_移动物体(self, 状态);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_删除物体(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);
		C_3D场景视口* view = static_cast<C_3D场景视口*>(self);

		if (!S_框架::g_变换开关) {
			f_ui_打开弹出窗口(m_3D视口删除弹出菜单, C_Widget::g_鼠标.gPos);
		}
	}
	return E_事件是否传递::e_事件传递_终止;
}




E_事件是否传递 f_工作区_切换摄像机投影模式(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		f_ui_切换开关状态(view.ui_透视模式组件);
		
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到激活物体中心(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto view = dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);
		f_camera_set摄像机视点移动到偏移点(*camera);

		S_Bounding bound{{2000000000,2000000000, 2000000000}, {-2000000000, -2000000000, -2000000000}};
	
		for (auto& e : S_框架::g_拾取物体) {
			vec3 最大 = e->m_包围盒.pos + e->m_包围盒.size;
			vec3 最小 = e->m_包围盒.pos - e->m_包围盒.size;

			bound.min = vec_Min(vec_Min(最大, 最小), bound.min);
			bound.max = vec_Max(vec_Max(最大, 最小), bound.max);
		}

		float32 最大大小 = length(bound.max - bound.min);
		if (最大大小 > 0) {
			camera->m_视距 = 最大大小 * 1.3;
		}
	
		f_view3d_缩放所有视口变换手柄();
		f_3D视口工作区_更新所有视口组件绘制();
	}
	return E_事件是否传递::e_事件传递_终止;
}


E_事件是否传递 f_工作区_镜头视点移动到左(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = 0;
		camera->m_变换.rotation.y = 90;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到右(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = 0;
		camera->m_变换.rotation.y = -90;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到上(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = -90;
		camera->m_变换.rotation.y = 0;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到下(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = 90;
		camera->m_变换.rotation.y = 0;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到前(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = 0;
		camera->m_变换.rotation.y = 0;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_镜头视点移动到后(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);

		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);

		camera->m_变换.rotation.x = 0;
		camera->m_变换.rotation.y = 180;
		camera->m_变换.rotation.z = 0;
		camera->m_isUpdate = true;
		view.f_更新方向组件(*camera);

		f_view3d_缩放所有视口变换手柄();
		f_widget_更新绘制(self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_设置激活摄像机为视口摄像机(C_Widget* self, E_键位执行状态 状态) {
	if (E_键位执行状态::e_开始 == 状态 && S_框架::g_变换开关 == false) {
		f_projectFile_设置文件保存状态(false);
	
		for (auto& ob : S_框架::g_拾取物体) {
			S_摄像机* camera = (S_摄像机*)f_ob_以类型查找子物体(ob, E_物体类型::t_摄像机);
			if (camera) {
				f_ui_set3D视口摄像机(self, camera);
				break;
			}
		}
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体单选(C_Widget* self, E_键位执行状态 状态) {
	f_projectFile_设置文件保存状态(false);

	C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);
	
	f_工作区_选择物体(工作区页面, false);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体加选(C_Widget* self, E_键位执行状态 状态) {
	f_projectFile_设置文件保存状态(false);

	C_工作区页面* 工作区页面 = static_cast<C_工作区页面*>(self);

	f_工作区_选择物体(工作区页面, true);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体框选排除(C_Widget* self, E_键位执行状态 状态) {
	static vec2 g选框起点坐标;
	static vec2 g选框终点坐标;

	auto& view = *dynamic_cast<C_3D场景视口*>(self);
	//std::cout<<"状态 = " << uint32(状态) <<std::endl;
	switch (状态) {
		case E_键位执行状态::e_开始:
			g选框起点坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		case E_键位执行状态::e_执行:
		case E_键位执行状态::e_完成:
			g选框终点坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
			f_view3d_框选物体(view, g选框起点坐标, g选框终点坐标, true, 状态);

			f_widget_更新渲染层(view.ui_操作图形层);
			//f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_拾取物体);
			break;
		default:
			break;
	}

	
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_物体框选(C_Widget* self, E_键位执行状态 状态) {
	static vec2 g选框起点坐标;
	static vec2 g选框终点坐标;

	if (S_框架::g_操作变换轴 == E_轴向::e_None轴向 && !S_框架::g_变换开关) {
		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		//std::cout<<"状态 = " << uint32(状态) <<std::endl;
		switch (状态) {
			case E_键位执行状态::e_开始:
				g选框起点坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
			case E_键位执行状态::e_执行:
			case E_键位执行状态::e_完成:
				g选框终点坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
				f_view3d_框选物体(view, g选框起点坐标, g选框终点坐标, false, 状态);

				f_widget_更新渲染层(view.ui_操作图形层);
				break;
			default:
				break;
		}

		return E_事件是否传递::e_事件传递_终止;
	}
	else {
		return E_事件是否传递::e_事件传递_继续;
	}
}

E_事件是否传递 f_工作区_物体反选(C_Widget* self, E_键位执行状态 状态) {
	switch (状态) {
		case E_键位执行状态::e_开始:
			f_OM_反选物体(S_框架::g_拾取物体, E_工作区类型::e_3D视口);
		break;
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_开启多选操作(C_Widget* self, E_键位执行状态 状态) {
	if (状态 == E_键位执行状态::e_完成) {
		C_3D场景视口::g加选 = false;
	}
	else {
		C_3D场景视口::g加选 = true;
	}
	
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_关闭多选操作(C_Widget* self, E_键位执行状态 状态) {
	C_3D场景视口::g加选 = false;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_打开关键帧插入菜单(C_Widget* self, E_键位执行状态 状态) {
	f_ui_打开弹出窗口(m_3D视口插帧弹出菜单, C_Widget::g_鼠标.gPos);
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_变换物体(C_Widget* self, E_键位执行状态 状态) {
	E_事件是否传递 事件是否传递 = E_事件是否传递::e_事件传递_继续;

	if (S_框架::g_变换开关 && !(C_3D场景视口::g视口摄像机平移 & C_3D场景视口::g_移动视口_键盘按键)) {
		auto& view = *dynamic_cast<C_3D场景视口*>(self);
		auto& str = f_prop_LineStr(view.m_数值输入显示);
		if(!str.empty()) return 事件是否传递;

		auto* camera = f_ui_get3D视口摄像机(view.ui_三维视口);
		auto rect = f_ui_get视口(self);
		auto 鼠标位置 = f_view3d_get平面鼠标位置(self);
		vec3 坐标 = { 鼠标位置.x, 鼠标位置.y, 0.0f };

		static vec2 轴线 = { 1,0 };
		vec3 手柄坐标 = view.m_变换手柄->f_get位置();

		switch (S_框架::g_物体变换方式) {
			case E_变换::e_移动: {
				vec3 视线向量 = -f_camera_get视线向量(*camera);

				vec3 移动{};
				vec3 当前射线[2];
				vec3 射线方向 = f_scene_构建屏幕射线(坐标, *camera, rect, 当前射线);
				
				

				if (S_框架::g_操作变换轴 == E_轴向::e_XYZ) {
					vec4 拾取平面 = f_graph_坐标构建平面(S_射线拾取参数::g手柄初始变换, 视线向量);
					f_graph_线段平面相交(当前射线[0], 当前射线[1], 拾取平面, S_射线拾取参数::g交点E);

					S_框架::g_变换手柄属性.position = S_射线拾取参数::g交点E;
					S_框架::g_变换手柄属性.position += g拾取点到手柄相对位置;
					移动 += g拾取点到手柄相对位置;
				}
				else {
					vec3 起点 = S_射线拾取参数::g手柄初始变换;
					vec3 眼睛位置 = f_camera_get眼睛位置(*camera);

					视线向量 = (眼睛位置 - 起点);
					switch (S_框架::g_操作变换轴) {
						case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
						case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
						case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;

						case E_轴向::e_XY: vec_mul(&视线向量, vec3{ 0, 0, 1 }); break;
						case E_轴向::e_XZ: vec_mul(&视线向量, vec3{ 0, 1, 0 }); break;
						case E_轴向::e_YZ: vec_mul(&视线向量, vec3{ 1, 0, 0 }); break;
					}
					视线向量 = normalize(视线向量);


					vec4 拾取平面 = f_graph_坐标构建平面(S_射线拾取参数::g手柄初始变换, 视线向量);
					f_graph_线段平面相交(当前射线[0], 当前射线[1], 拾取平面, S_射线拾取参数::g交点E);
					S_框架::g_变换手柄属性.position = S_射线拾取参数::g交点E;
					移动 = S_射线拾取参数::g交点E;

					vec3 移动缩放 = view.m_变换手柄->m_变换.scale;
					//vec3 移动缩放 = {1,1,1};
					
					//std::cout<<"**-----------**-----------**-------------移动 x = " << 移动.x <<" y = " << 移动.y <<" z = " << 移动.z << std::endl;
					//std::cout<<"起点 x = " << 起点.x <<" y = " << 起点.y <<" z = " << 起点.z << std::endl;
					f_控制手柄_锁定步进位置(S_框架::g_变换手柄属性.position, 起点);
					f_控制手柄_锁定步进位置(移动, 起点);

					//std::cout<<"S_框架::g_操作变换轴 = " << S_框架::g_操作变换轴 << std::endl;
					//std::cout<<"-- ** -- g_变换手柄属性 x = " << S_框架::g_变换手柄属性.position.x <<" y = " << S_框架::g_变换手柄属性.position.y <<" z = " << S_框架::g_变换手柄属性.position.z << std::endl;


					switch (S_框架::g_操作变换轴) {
						case E_轴向::e_X: S_框架::g_变换手柄属性.position.x += g拾取点到手柄相对位置.x * 移动缩放.x; 移动.x += g拾取点到手柄相对位置.x; break;
						case E_轴向::e_Y: S_框架::g_变换手柄属性.position.y += g拾取点到手柄相对位置.y * 移动缩放.y; 移动.y += g拾取点到手柄相对位置.y; break;
						case E_轴向::e_Z: S_框架::g_变换手柄属性.position.z += g拾取点到手柄相对位置.z * 移动缩放.z; 移动.z += g拾取点到手柄相对位置.z; break;

						case E_轴向::e_XY: 
							S_框架::g_变换手柄属性.position.x += g拾取点到手柄相对位置.x * 移动缩放.x; 移动.x += g拾取点到手柄相对位置.x;
							S_框架::g_变换手柄属性.position.y += g拾取点到手柄相对位置.y * 移动缩放.y; 移动.y += g拾取点到手柄相对位置.y;
							break;
						case E_轴向::e_XZ: 
							S_框架::g_变换手柄属性.position.x += g拾取点到手柄相对位置.x * 移动缩放.x; 移动.x += g拾取点到手柄相对位置.x;
							S_框架::g_变换手柄属性.position.z += g拾取点到手柄相对位置.z * 移动缩放.z; 移动.z += g拾取点到手柄相对位置.z;
							break;
						case E_轴向::e_YZ: 
							S_框架::g_变换手柄属性.position.y += g拾取点到手柄相对位置.y * 移动缩放.y; 移动.y += g拾取点到手柄相对位置.y;
							S_框架::g_变换手柄属性.position.z += g拾取点到手柄相对位置.z * 移动缩放.z; 移动.z += g拾取点到手柄相对位置.z;
							break;
					}

					//std::cout<<"g拾取点到手柄相对位置 x = " << g拾取点到手柄相对位置.x <<" y = " << g拾取点到手柄相对位置.y <<" z = " << g拾取点到手柄相对位置.z << std::endl;
					//std::cout<<"-- ** -- g_变换手柄属性 x = " << S_框架::g_变换手柄属性.position.x <<" y = " << S_框架::g_变换手柄属性.position.y <<" z = " << S_框架::g_变换手柄属性.position.z << std::endl;
					//std::cout<<"移动缩放 x = " << 移动缩放.x <<" y = " << 移动缩放.y <<" z = " << 移动缩放.z << std::endl;
					//std::cout<<"移动 x = " << 移动.x <<" y = " << 移动.y <<" z = " << 移动.z << std::endl;
				}
				

				f_变换_移动物体(S_框架::g_变换手柄属性.position);
				事件是否传递 = E_事件是否传递::e_事件传递_终止;
				break;
			}


			case E_变换::e_旋转: {
				vec2 coord = f_Project空间坐标转屏幕(*(Mat44f*)&camera->m_相机投影矩阵, *(Mat44f*)&camera->m_相机视图矩阵, 手柄坐标, rect);
				float32 旋转弧度 = view.f_旋转辅助线绘制(coord, 鼠标位置);

				vec3 视线向量;
				int32 方向 = f_控制手柄_旋转视线向量(camera, 视线向量);
				
				S_框架::g_变换手柄属性 = f_控制手柄_视线旋转物体(视线向量, 旋转弧度, 方向);
				事件是否传递 = E_事件是否传递::e_事件传递_终止;
				break;
			}

			case E_变换::e_缩放: {
				vec2 coord = f_Project空间坐标转屏幕(*(Mat44f*)&camera->m_相机投影矩阵, *(Mat44f*)&camera->m_相机视图矩阵, 手柄坐标, rect);
				float32 缩放 = view.f_缩放辅助线绘制(coord, 鼠标位置);

				S_框架::g_变换手柄属性 = f_控制手柄_全局缩放物体(S_框架::g_操作变换轴, 缩放);
				//f_控制手柄_局部缩放物体(S_框架::g_操作变换轴, 缩放);
				事件是否传递 = E_事件是否传递::e_事件传递_终止;
				break;
			}
		}

		f_view3d_置变换手柄变换(S_框架::g_变换手柄属性);
		f_view3d_缩放所有视口变换手柄();
		f_view3d_更新属性栏();
		f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_变换物体);

		f_widget_更新渲染层(view.ui_操作图形层);
		f_widget_更新绘制(self);
	}


	return 事件是否传递;
}

E_事件是否传递 f_工作区_打开创建菜单(C_Widget* self, E_键位执行状态 状态) {
	C_3D场景视口::g视口摄像机旋转 = false;
	if (状态 == E_键位执行状态::e_完成) {
		f_ui_打开弹出窗口(m_3D视口创建弹出菜单, C_Widget::g_鼠标.gPos, self);
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_方向小组件点击(C_Widget* self, E_键位执行状态 状态) {
	C_3D场景视口& view = *dynamic_cast<C_3D场景视口*>(self->m_父部件->m_父部件);

	if (!C_3D场景视口::g视口摄像机旋转 && !C_3D场景视口::g视口摄像机平移) {
		switch (view.m_方向小组件_选中的ID) {	
			case 3: f_工作区_镜头视点移动到左(view.ui_三维视口, 状态); break;
			case 1: f_工作区_镜头视点移动到上(view.ui_三维视口, 状态); break;
			case 5: f_工作区_镜头视点移动到前(view.ui_三维视口, 状态); break;

			case 0: f_工作区_镜头视点移动到右(view.ui_三维视口, 状态); break;
			case 4: f_工作区_镜头视点移动到下(view.ui_三维视口, 状态); break;
			case 2: f_工作区_镜头视点移动到后(view.ui_三维视口, 状态); break;
		
			default:
				break;
		}
	}
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_方向小组件_旋转摄像机(C_Widget* self, E_键位执行状态 状态) {
	return E_事件是否传递::e_事件传递_终止;
}



E_事件是否传递 f_view3d_物体添加到渲染层(C_Widget* self, E_键位执行状态 状态) {
	S_菜单创建参数 创建项;

	创建项.mf_菜单项点击 = on_1级菜单项_物体渲染层菜单项创建;
	for (auto& e : S_节点数据::g_渲染世界数据) {
		创建项.item.push_back({e.first, u"", 0});
	}
	
	f_ui_填充菜单项(g3D视口弹出菜单_渲染世界, 创建项, 1);

	f_ui_打开弹出窗口(g3D视口弹出菜单_渲染世界, C_Widget::g_鼠标.gPos);
	return E_事件是否传递::e_事件传递_终止;
}



E_事件是否传递 f_工作区_物体数据编辑(C_Widget* self, E_键位执行状态 状态) {

	switch (S_框架::g当前编辑对象类型) {
	case E_物体类型::t_网格物体: {
		switch (f_prop_enum(S_节点数据状态::g_网格编辑模式)) {
			case E_网格编辑模式::e_网格编辑_顶点: {
				break;
			}
			case E_网格编辑模式::e_网格编辑_权重: {
				//std::cout << "刷权重" << std::endl;
				break;
			}
			case E_网格编辑模式::e_网格编辑_纹理: {
				break;
			}
			default:
				break;
		}
		break;
	}
	case E_物体类型::t_骨架:
	case E_物体类型::t_骨骼: {
		if (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
		}
		else {
		}
		break;
	}
	
	case E_物体类型::t_摄像机: {
		break;
	}
	default:
		break;
	}

	return E_事件是否传递::e_事件传递_继续;
}





void f_3D视口工作区_置物体焦点() {
	vec3 中心坐标 = f_global_get激活物体包围中心点();
	
	for (auto& e : C_3D场景视口::gui_3D视口) {
		auto* camera = f_ui_get3D视口摄像机(e->ui_三维视口);
		e->m_变换手柄->f_set位置(中心坐标);
		f_camera_set偏移视点(*camera, 中心坐标);
	}

	f_view3d_缩放所有视口变换手柄();
}


void f_3D视口工作区_更新渲染物体() {
	if(S_光追后端::g_渲染状态) return;


}

void f_3D视口工作区_重置() {
	for (auto& e : C_3D场景视口::gui_3D视口) {
		auto* cameera = f_ui_get3D视口摄像机(e->ui_三维视口);
		
		cameera->m_视距 = 10;
		cameera->m_视点 = {};
		cameera->m_视点偏移 = {};
		cameera->f_set旋转(-20,-20,0);

		f_widget_更新绘制(e);
	}

	f_3D视口工作区_置物体焦点();
}

void f_3D视口工作区_销毁() {
	for (auto& e : C_3D场景视口::gui_3D视口) {
		f_ui_3D视口关闭渲染(e->ui_三维视口);
	}
	C_3D场景视口::gui_3D视口.clear();
}

void f_3D视口工作区_更新所有视口组件绘制() {
	for (auto& e : C_3D场景视口::gui_3D视口) {
		if (!e->m_被裁剪) {
			f_widget_更新绘制(e);
			f_widget_更新渲染层(e->ui_属性栏);
			f_widget_更新渲染层(e->ui_操作图形层);
		}
	}
}

void f_3D视口工作区_更新所有视口属性绘制() {
	for (auto& e : C_3D场景视口::gui_3D视口) {
		if (!e->m_被裁剪) {
			f_widget_更新渲染层(e->ui_属性栏);
		}
	}
}

void f_3D视口工作区_更新所有视口属性面板() {
	for (auto& e : C_3D场景视口::gui_3D视口) {
		if (!e->m_被裁剪) {
			f_view3d_重构属性栏(e->ui_属性栏, S_框架::g_拾取物体, e->ui_三维视口);
			//f_widget_更新渲染层(e->ui_属性栏);
		}
	}
}

void f_3D视口工作区页面_联动更新(E_工作区类型 来源工作区类型, E_工作区操作类型 操作类型) {

}






void f_3D视口工作区_保存工作区状态(FILE* f, C_工作区页面* 页面) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(页面->mui_视口页面);
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_工作区页面布局, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_文件块_写数据块(块, camera->m_变换);
	f_文件块_写数据块(块, camera->m_视点);
	f_文件块_写数据块(块, camera->f_get视点偏移());
	f_文件块_写数据块(块, camera->m_视距);
	f_文件块_写数据块(块, camera->m_投影模式);

	f_file_保存文件块(f, 文件块, 块);
}

void f_3D视口工作区_加载工作区状态(FILE* f, C_工作区页面* 页面) {
	C_3D场景视口* view = static_cast<C_3D场景视口*>(页面->mui_视口页面);
	auto* camera = f_ui_get3D视口摄像机(view->ui_三维视口);

	S_文件块 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_工作区页面布局) {
		
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, camera->m_变换);
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, camera->m_视点);
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, camera->f_get视点偏移());
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, camera->m_视距);
			下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, camera->m_投影模式);
		}
	}

	free(文件块.m_data);
}













